home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1991
/
06
/
alib
/
block.asm
< prev
next >
Wrap
Assembly Source File
|
1990-10-31
|
16KB
|
754 lines
title block storage manager
include asm.inc
public block_alloc
public block_file_open
public block_file_read
public block_free
public block_read
BLOCK_MAX equ 512
FIRST_BLOCK equ 08000h ; block handles start at 0x8000
NULL_BLOCK equ 0
NULL_EMS equ 0
NULL_ID equ 0
NULL_SWAP equ 0
OPEN_LINK equ 0FFFFh
block_str struc
blk_forward dw ? ; forward link for LRU
blk_backward dw ? ; backward link
blk_pointer dd ? ; RAM address (or 0 if in EMS or DISK)
blk_ems_index dw ? ; EMS index
blk_swap_index dw ? ; swap file index (0 if not swapped)
blk_file_id dw ? ; file identification (0 if not in file)
blk_file_index dw ? ; file block index
blk_file_link dw ? ; blocks for each file form a list
blk_byte_count dw ? ; (file blocks may be less than 16k)
block_str ends ; (structure must be even number of bytes)
XIB segment word public 'DATA' ; initialize block manager
XIB ends
XI segment word public 'DATA'
dw block_preset
XI ends
XIE segment word public 'DATA'
XIE ends
.const
ertx_block_handle db 'Bad block handle',0
ertx_empty_file db 'Cannot map empty file',0
ertx_free_block db 'Cannot free block',0
ertx_past_eof db 'Block read past EOF',0
ertx_virtual_full db 'Virtual memory full',0
.data?
block_table dd ? ; array of block structures
ram_front dw ? ; LRU list of RAM blocks
ram_back dw ?
ems_front dw ? ; LRU list of EMS blocks
ems_back dw ?
free_front dw ? ; free handle stack
free_count dw ? ; number of free blocks
file_blocks dw ? ; # of blocks in file (see block_file_open)
.code
extn abort_if_cf,calloc,clear_strerror,ems_exchange,ems_in,swap_in
extn ems_out,free,malloc,save_most,set_strerror,swap_out,check_block_file
extn open_block_file,read_block_file,set_block_handle
page
;; access block table
;
; entry BX block handle
; exit DS:SI block table entry for handle
; Cf if bad handle
; uses AX
;
access_block_table proc
mov ax,bx
sub ax,FIRST_BLOCK
jb abt1 ; if bad handle
cmp ax,BLOCK_MAX
jae abt1 ; if bad handle
mov si,dx
mov dx,size block_str
mul dx
mov dx,si
lds si,block_table[bp]
add si,ax
ret
abt1: lea ax,ertx_block_handle ; *Bad block handle*
jmp set_strerror
access_block_table endp
;; block alloc
;
; exit AX block size in bytes
; BX block handle
; ES:DI block pointer
; Cf if no memory
;
block_alloc proc
pushm si,ds
call malloc_storage_block
jc bal2 ; if no memory
call new_block_handle
jc bal1 ; if no more block handles
mov wptr blk_pointer[si],di
mov wptr blk_pointer[si+2],es
call set_mru_ram ; set most recently used
mov ax,BLOCK_SIZE
mov blk_byte_count[si],ax
clc
jmp bal3
bal1: call free ; here when out of handles, free
bal2: movx bx,NULL_BLOCK ; storage and return error
stc
bal3: popm ds,si
ret
block_alloc endp
;; block file open
;
; entry DS:SI file name
; exit AX file size in blocks
; BX block handle
; Cf if file not found or empty
;
block_file_open proc
pushm cx,dx,di,si,ds
call check_block_file
jnc bfo4 ; if existing file
bfo1: call open_block_file
jc bfo4 ; if file not found
jcxz bfo7 ; if empty file
cmp cx,free_count[bp]
ja bfo5 ; if not enough blocks for file
mov file_blocks[bp],cx
movx cx,0
call new_file_block ; allocate first file block
jc bfo4
mov bx,ax
cmp cx,file_blocks[bp]
je bfo3 ; if file size <= 16k
bfo2: mov di,si
call new_file_block
jc bfo4
mov blk_file_link[di],si
cmp cx,file_blocks[bp]
jb bfo2
call set_block_handle ; save handle in case we open again
bfo3: mov ax,file_blocks[bp] ; return file size (Cf unchanged)
bfo4: popm ds,si,di,dx,cx
ret
bfo5: lea ax,ertx_virtual_full ; *Virtual memory full*
bfo6: call set_strerror
jmp bfo4
bfo7: lea ax,ertx_empty_file ; *Cannot map empty file*
jmp bfo6
block_file_open endp
;; block file read
;
; entry AX 16k file block number (0..n)
; BX block index
; exit DS:SI block pointer
; AX block size (<16k if last block)
; Cf if bad block index or past end of file
;
block_file_read proc
push cx
mov cx,ax
call access_block_table
jc bfr4
jcxz bfr2 ; if first block
bfr1: mov si,blk_file_link[si] ; else chase linked list to
cmp si,OPEN_LINK ; selected blk
loopne bfr1
je bfr3 ; if block number too large
bfr2: pop cx
jmp block_read_primitive
bfr3: lea ax,ertx_past_eof ; *Block read past EOF*
call set_strerror
bfr4: pop cx
ret
block_file_read endp
;; block free
;
; entry BX block index
; exit Cf if bad index (cannot free file blocks)
; uses AX,BX
;
block_free proc
pushm di,si,ds,es
call access_block_table
jc bfe5
cmp blk_file_id[si],NULL_ID ; illegal to free a file block
jne bfe6 ; if file block
les di,blk_pointer[si]
mov ax,es
or ax,di
jz bfe1 ; if not in RAM
call unlink_ram_list ; unlink block from RAM LRU list
call free ; free storage
jmp bfe3
bfe1: mov ax,blk_ems_index[si]
cmpx ax,NULL_EMS
je bfe2 ; if not in EMS
call ems_in ; free EMS block (ES:DI==NULL)
call unlink_ems_list ; unlink block from EMS LRU list
jmp bfe3
bfe2: mov ax,blk_swap_index[si]
cmpx ax,NULL_SWAP
je bfe6 ; if not in swap file (thus error)
call swap_in ; free swap block (ES:DI==NULL)
bfe3: mov bx,size block_str ; clear block table entry and
bfe4: dec bx ; leave BX==0
dec bx
mov wptr [si+bx],ZER0
jnz bfe4
mov ax,si ; link onto free block stack
xchg ax,free_front[bp]
mov blk_backward[si],ax
inc free_count[bp]
clc
bfe5: popm es,ds,si,di ; (POP xS could fault in protect mode)
ret
bfe6: lea ax,ertx_free_block ; *Cannot free block*
call set_strerror
jmp bfe5
block_free endp
;; block preset
;
; uses AX
;
block_preset proc
call save_most ; allocate block table
mov cx,BLOCK_MAX*size block_str
call calloc ; (must have NULL offset)
call abort_if_cf
mov wptr block_table[bp],di
mov wptr block_table[bp+2],es
mov ax,OPEN_LINK ; build free list
mov cx,BLOCK_MAX
mov free_count[bp],cx
lds si,block_table[bp]
mov free_front[bp],si
bps1: lea dx,[si+size block_str]
mov blk_backward[si],dx
mov blk_forward[si],ax
mov blk_file_link[si],ax
xchg dx,si
loop bps1
mov blk_backward[si-size block_str],ax
mov ram_front[bp],ax ;\initialize LRU lists for RAM and EMS
mov ram_back[bp],ax
mov ems_front[bp],ax
mov ems_back[bp],ax
ret
block_preset endp
;; block read
;
; entry BX block index
; exit AX block size
; DS:SI block pointer
; Cf if bad block or no memory
;
block_read proc
call access_block_table
jnc block_read_primitive ;\
ret ;\
block_read endp
;; block read primitive
;
; entry DS:SI block table pointer
; exit AX block size
; DS:SI block pointer
; Cf if bad block or no memory
;
block_read_primitive proc
pushm di,es
cmp wptr blk_pointer[si+2],NULL_POINTER
je brp1 ; if block is not in RAM
call reset_mru_ram ; move to front of LRU list
jmp brp5
brp1: call malloc_storage_block ; allocate storage for block
jc brp6 ; if no memory
mov ax,blk_ems_index[si] ; check if block swapped to EMS
cmpx ax,NULL_EMS
je brp2 ; if not in EMS
call ems_in ; else swap block in from EMS
jc brp8 ; if unexpected EMS error
call unlink_ems_list ; delete from EMS LRU list
mov blk_ems_index[si],NULL_EMS
jmp brp4
brp2: cmp blk_file_id[si],NULL_ID ; check if file block
je brp3 ; if not
push bx ; else read block from file
mov bx,blk_file_id[si]
mov ax,blk_file_index[si]
call read_block_file
pop bx
jc brp8 ; if error reading file
mov blk_byte_count[si],ax
jmp brp4 ; else read OK
brp3: mov ax,blk_swap_index[si] ; check if block swapped out
cmpx ax,NULL_SWAP
je brp7 ; if not swapped - bad block handle
call swap_in
jc brp8 ; if error swapping block in
mov blk_swap_index[si],NULL_SWAP
brp4: mov wptr blk_pointer[si],di ; save RAM pointer in block table
mov wptr blk_pointer[si+2],es
call set_mru_ram ; move to front of LRU list
brp5: mov ax,blk_byte_count[si] ; return RAM pointer and byte count
lds si,blk_pointer[si]
clc
brp6: popm es,di
ret
brp7: lea ax,ertx_block_handle ; *Bad block handle*
call set_strerror
brp8: call free
stc
jmp brp6
block_read_primitive endp
;; free ram block
;
; exit Cf if no RAM free
; uses AX
;
free_ram_block proc
call save_most
call get_lru_ram ; get least recently used memory block
jc frb4 ; if no blocks on LRU list
les di,blk_pointer[si] ; else file block, swap to EMS
call ems_out
jc frb2 ; if unable to swap to EMS
mov blk_ems_index[si],ax ; else save EMS page index
call set_mru_ems
frb1: call free ; free storage
jc frb4 ; if unexpected error
mov wptr blk_pointer[si],di ; (free returns with ES:DI==NULL)
mov wptr blk_pointer[si+2],es
jmp frb4
frb2: call clear_strerror ; here when EMS is full
cmp blk_file_id[si],NULL_ID ; is block file or storage?
jne frb1 ; if file block - just free its ram
mov bx,si ; try exchanging RAM block & LRU EMS
call get_lru_ems
jc frb3 ; if no EMS (SI still -> RAM block)
mov ax,blk_ems_index[si]
call ems_exchange ; (ES:DI still points to RAM block)
jc frb4 ; if exchange failed (serious error)
movx ax,NULL_EMS ; exchange EMS index and RAM pointers
xchg ax,blk_ems_index[si] ; for exchanged blocks
mov blk_ems_index[bx],ax
mov wptr blk_pointer[bx],NULL_POINTER
mov wptr blk_pointer[bx+2],NULL_POINTER
mov wptr blk_pointer[si],di
mov wptr blk_pointer[si+2],es
xchg bx,si ; set most recently used EMS block
call set_mru_ems
xchg bx,si
frb3: call swap_out ; write block to swap file
mov blk_swap_index[si],ax ; set swap index (or 0 if failure)
jnc frb1 ; if swapped OK
call set_lru_ram ; swap failed, re-link RAM block
movx bx,NULL_BLOCK
stc
frb4: ret
free_ram_block endp
;; get lru ems
;
; exit DS:SI least recently used block in EMS
; Cf if no blocks in EMS (SI unchanged)
; uses AX
;
get_lru_ems proc
mov ax,OPEN_LINK
cmp ax,ems_back[bp]
je gle2 ;\ if no EMS blocks
lds si,block_table[bp]
mov si,ems_back[bp]
cmp si,ems_front[bp]
je gle1 ; if only one EMS block
push bx
mov bx,blk_forward[si]
mov blk_backward[bx],ax
mov ems_back[bp],bx
pop bx
clc
ret
gle1: mov ems_front[bp],ax
mov ems_back[bp],ax
ret ; (Cf==0)
gle2: stc
ret
get_lru_ems endp
;; get lru ram
;
; exit DS:SI least recently used block in RAM
; Cf if no unlocked blocks in RAM
; uses AX
;
get_lru_ram proc
mov ax,OPEN_LINK
lds si,block_table[bp]
mov si,ram_back[bp]
cmp si,ax
je glr2 ; if no RAM blocks
cmp si,ram_front[bp]
je glr1 ; if only one RAM block
push bx
mov bx,blk_forward[si]
mov blk_backward[bx],ax
mov ram_back[bp],bx
pop bx
clc
ret
glr1: mov ram_front[bp],ax
mov ram_back[bp],ax
ret ; (Cf==0)
glr2: stc
ret
get_lru_ram endp
;; malloc storage block
;
; exit ES:DI storage block
; Cf if unable to allocate storage
; uses AX
;
malloc_storage_block proc
push cx
mov cx,BLOCK_SIZE ; allocate block of memory
call malloc
jnc msb1 ; if OK
call clear_strerror ; clear malloc error
call free_ram_block ; swap to EMS or disk to free ram
jc msb1 ; if too many locked blocks
call malloc ; try malloc one more time
msb1: pop cx
ret
malloc_storage_block endp
;; new block handle
;
; exit BX block handle
; DS:SI block table entry
; Cf if no free handles
; uses AX
;
new_block_handle proc
lds si,block_table[bp] ; get first block from free list
mov si,free_front[bp]
cmp si,OPEN_LINK
je nbh1 ; if no more handles
mov ax,blk_backward[si]
mov free_front[bp],ax
dec free_count[bp]
push dx ; compute handle from table offset
mov ax,si
movx dx,0
mov bx,size block_str
div bx
add ax,FIRST_BLOCK
mov bx,ax
pop dx
ret
nbh1: lea ax,ertx_virtual_full ; *Virtual memory full*
jmp set_strerror
new_block_handle endp
;; new file block
;
; entry CX block number
; DX file id
; exit AX block handle
; CX +1
; DS:SI block table entry
; Cf if no more blocks
;
new_file_block proc
push bx
call new_block_handle ; allocate block
jc nfb1 ; if no more blocks
mov blk_file_id[si],dx ; set file id and block number
mov blk_file_index[si],cx
inc cx
mov ax,OPEN_LINK ; reset links
mov blk_file_link[si],ax
mov blk_forward[si],ax
mov blk_backward[si],ax
mov ax,bx ;\
nfb1: pop bx
ret
new_file_block endp
;; reset mru ram
;
; entry DS:SI most recently used table entry
; uses AX
;
reset_mru_ram proc
cmp si,ram_front[bp]
je rmr4 ; if already most recently used
push bx
cmp si,ram_back[bp]
je rmr1 ; if least recently used
mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp rmr2
rmr1: call get_lru_ram ; delete from back of LRU list
jc rmr3 ; if internal error
rmr2: call set_mru_ram
clc
rmr3: pop bx
rmr4: ret
reset_mru_ram endp
;; set lru ram
;
; entry DS:SI least recently used table entry
; uses AX,BX
;
set_lru_ram proc
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ram_back[bp]
cmp bx,ax
je slr1 ; if empty list
mov blk_backward[si],ax ; else link onto back of list
mov blk_forward[si],bx
mov blk_backward[bx],si
ret
slr1: mov ram_front[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
ret
set_lru_ram endp
;; set mru ems
;
; entry DS:SI most recently used table entry
; uses AX
;
set_mru_ems proc
push bx
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ems_front[bp]
cmp bx,ax
je sme1 ; if empty list
mov blk_forward[si],ax ; else link onto front of list
mov blk_backward[si],bx
mov blk_forward[bx],si
pop bx
ret
sme1: mov ems_back[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
pop bx
ret
set_mru_ems endp
;; set mru ram
;
; entry DS:SI most recently used table entry
; uses AX
;
set_mru_ram proc
push bx
mov ax,OPEN_LINK ; check for empty list
mov bx,si
xchg bx,ram_front[bp]
cmp bx,ax
je smr1 ; if empty list
mov blk_forward[si],ax ; else link onto front of list
mov blk_backward[si],bx
mov blk_forward[bx],si
pop bx
ret
smr1: mov ram_back[bp],si ; create list with one element
mov blk_forward[si],ax
mov blk_backward[si],ax
pop bx
ret
set_mru_ram endp
;; unlink ems list
;
; entry DS:SI block table entry
; uses AX
;
unlink_ems_list proc
cmp si,ems_back[bp]
je uel1 ; if EMS block is LRU
push bx
cmp si,ems_front[bp]
je uel2 ; if EMS block is MRU
mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp uel3
uel1: jmp get_lru_ems
uel2: mov bx,blk_backward[si] ; delete from front of LRU list
mov blk_forward[bx],OPEN_LINK
mov ems_front[bp],bx
uel3: pop bx
ret
unlink_ems_list endp
;; unlink ram list
;
; entry DS:SI block table entry
; uses AX
;
unlink_ram_list proc
cmp si,ram_back[bp]
je url1 ; if RAM block is LRU
push bx
cmp si,ram_front[bp]
je url2 ; if RAM block is MRU
mov ax,blk_forward[si] ; delete from middle of LRU list
mov bx,blk_backward[si]
mov blk_forward[bx],ax
xchg ax,bx
mov blk_backward[bx],ax
jmp url3
url1: jmp get_lru_ram
url2: mov bx,blk_backward[si] ; delete from front of LRU list
mov blk_forward[bx],OPEN_LINK
mov ram_front[bp],bx
url3: pop bx
ret
unlink_ram_list endp
end